package com.gph.saviorframework.security.web.controller;

import com.github.pagehelper.PageHelper;
import com.gph.saviorframework.Constants;
import com.gph.saviorframework.ErrorCode;
import com.gph.saviorframework.SaviorFrameworkException;
import com.gph.saviorframework.common.model.Org;
import com.gph.saviorframework.security.service.OrgService;
import com.gph.saviorframework.security.web.editor.OrgEditor;
import com.gph.saviorframework.util.RequestUtil;
import com.gph.saviorframework.util.SecurityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.support.MessageSourceAccessor;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.ServletRequestDataBinder;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * Created by iscas-qd on 2016/3/19.
 */
@Controller
@RequestMapping("/" + Constants.FRAMEWORK_REQUEST_PATH + "/org")
public class OrgController {

    /** 日志输出 */
    final Logger logger = LoggerFactory.getLogger(OrgController.class);

    /** 领域对象名称 */
    private String domain = Org.class.getSimpleName().toLowerCase();

    /** 视图前缀 */
    private String viewPrefix = Constants.FRAMEWORK_REQUEST_PATH + "/" + Constants.MODULE_CATEGORY_SECURITY + "/" + domain + "/" + domain + "_";

    @Autowired
    private OrgService orgService;

    @Autowired
    private SecurityUtils securityUtils;

    @Autowired
    private MessageSourceAccessor messages;

    @InitBinder
    public void initBinder(WebDataBinder binder) {
        binder.registerCustomEditor(Org.class, new OrgEditor(orgService));
    }

    @RequestMapping(value = "/index", method = RequestMethod.GET)
    public String indexPage() throws SaviorFrameworkException {
        return viewPrefix + "index";
    }

    @RequestMapping(value = "/index", method = RequestMethod.POST)
    @ResponseBody
    public ModelMap list(
            @RequestParam(value = Constants.DEFAULT_PAGE_MODEL_KEY, required = false, defaultValue = Constants.DEFAULT_PAGE_START) Integer start,
            @RequestParam(value = Constants.DEFAULT_RECORD_MODEL_KEY, required = false, defaultValue = Constants.DEFAULT_PAGE_SIZE) Integer limit,
            @RequestParam(value = Constants.DEFAULT_SORT_MODEL_KEY, required = false, defaultValue = Constants.DEFAULT_SORT_FIELD) String sort,
            @RequestParam(value = Constants.DEFAULT_DIR_MODEL_KEY, required = false, defaultValue = Constants.DEFAULT_SORT_DIRECTION) String dir,
            @RequestParam(value = "parent", required = false, defaultValue = "")
            String parent, HttpServletRequest request)
            throws SaviorFrameworkException {
        ModelMap modelMap = new ModelMap();
        Map<String, Object> params = RequestUtil.getQueryMap(request, orgService.getFields());
        try {
            PageHelper.startPage(start,limit);
            modelMap.addAttribute(Constants.DEFAULT_RECORD_MODEL_KEY, orgService.find(parent, sort, dir, params));
            modelMap.addAttribute(Constants.DEFAULT_COUNT_MODEL_KEY, orgService.count(parent, params));
            modelMap.addAttribute(Constants.DEFAULT_SUCCESS_KEY, Boolean.TRUE);
            logger.info(messages.getMessage("log.info.list", new String[]{securityUtils.getUserFullName(), messages.getMessage(domain)}));
        } catch (DataAccessException e) {
            e.printStackTrace();
            modelMap.addAttribute(Constants.DEFAULT_SUCCESS_KEY, Boolean.FALSE);
            logger.error(messages.getMessage("log.error.list", new String[]{securityUtils.getUserFullName(), messages.getMessage(domain)}));
        }
        return modelMap;
    }

    @RequestMapping(value = "/create", method = RequestMethod.GET)
    public String create() throws SaviorFrameworkException {
        return viewPrefix + "create";
    }

    /**
     * 保存新建数据
     *
     * @param org 数据对象
     * @return
     * @throws SaviorFrameworkException
     */
    @RequestMapping(value = "/create", method = RequestMethod.POST)
    @ResponseBody
    public ModelMap create(@ModelAttribute Org org) throws SaviorFrameworkException {
        ModelMap modelMap = new ModelMap();
        try {
            securityUtils.setCreateEntity(org);
            org.setVersion(Constants.VERSION_INIT_VALUE);
            org.setId(orgService.getKey());
            org.setEnabled(true);
            orgService.save(org);
            modelMap.addAttribute(Constants.DEFAULT_SUCCESS_KEY, Boolean.TRUE);
            modelMap.addAttribute(Constants.DEFAULT_ID_KEY, org.getId());
            logger.info(messages.getMessage("log.info.create",
                    new String[] { securityUtils.getUserFullName(), messages.getMessage(domain), org.getId() }));
        }
        catch (Exception e) {
            e.printStackTrace();
            modelMap.addAttribute(Constants.DEFAULT_SUCCESS_KEY, Boolean.FALSE);
            modelMap.addAttribute(Constants.DEFAULT_ERROR_KEY, e.getMessage());
            logger.error(messages.getMessage("log.error.create", new String[] { securityUtils.getUserFullName(), messages.getMessage(domain) }));
        }
        return modelMap;
    }

    @RequestMapping(value = "/edit", method = RequestMethod.GET)
    public String edit() throws SaviorFrameworkException {
        return viewPrefix + "edit";
    }

    @RequestMapping(value = "/edit/{id}", method = RequestMethod.POST)
    @ResponseBody
    public ModelMap edit(@PathVariable("id") String id, HttpServletRequest request) throws SaviorFrameworkException {
        ModelMap modelMap = new ModelMap();
        try {
            Org org = orgService.get(id);
            ServletRequestDataBinder binder = new ServletRequestDataBinder(org);
            binder.registerCustomEditor(Org.class, new OrgEditor(orgService));
            binder.bind(request);
            securityUtils.setModifyEntity(org);
            org.setVersion(org.getVersion() + 1);
            orgService.update(org);
            modelMap.addAttribute(Constants.DEFAULT_SUCCESS_KEY, Boolean.TRUE);
            logger.info(messages.getMessage("log.info.edit", new String[]{securityUtils.getUserFullName(), messages.getMessage(domain), id}));
        }
        catch (Exception e) {
            e.printStackTrace();
            modelMap.addAttribute(Constants.DEFAULT_SUCCESS_KEY, Boolean.FALSE);
            modelMap.addAttribute(Constants.DEFAULT_ERROR_KEY, e.getMessage());
            logger.error(messages.getMessage("log.error.edit", new String[] { securityUtils.getUserFullName(), messages.getMessage(domain), id }));
        }
        return modelMap;
    }

    @RequestMapping(value = "/view/{id}", method = RequestMethod.GET)
    @ResponseBody
    public ModelMap get(@PathVariable("id") String id) throws SaviorFrameworkException {
        ModelMap modelMap = new ModelMap();
        try {
            modelMap.addAttribute(Constants.DEFAULT_RECORD_MODEL_KEY, orgService.findById(id));
            modelMap.addAttribute(Constants.DEFAULT_SUCCESS_KEY, Boolean.TRUE);
        }
        catch (Exception e) {
            e.printStackTrace();
            modelMap.addAttribute(Constants.DEFAULT_SUCCESS_KEY, Boolean.FALSE);
            modelMap.addAttribute(Constants.DEFAULT_ERROR_KEY, e.getMessage());
        }
        return modelMap;
    }

    @RequestMapping(value = "/delete", method = RequestMethod.POST)
    @ResponseBody
    public ModelMap delete(@RequestParam(value = "ids", required = true) String[] ids) throws SaviorFrameworkException {
        ModelMap modelMap = new ModelMap();
        try {
            orgService.deleteByIds(ids);
            modelMap.addAttribute(Constants.DEFAULT_SUCCESS_KEY, Boolean.TRUE);
            logger.info(messages.getMessage("log.info.delete", new String[]{securityUtils.getUserFullName(), messages.getMessage(domain),
                    StringUtils.arrayToDelimitedString((Object[]) ids, "|")}));
        } catch (DataIntegrityViolationException e) {
            e.printStackTrace();
            modelMap.addAttribute(Constants.DEFAULT_SUCCESS_KEY, Boolean.FALSE);
            modelMap.addAttribute(Constants.DEFAULT_ERROR_KEY, ErrorCode.DATA_INTEGRITY_VIOLATION);
            logger.error(messages.getMessage("log.error.delete", new String[] { securityUtils.getUserFullName(), messages.getMessage(domain),
                    StringUtils.arrayToDelimitedString((Object[]) ids, "|") }));
        } catch (Exception e) {
            e.printStackTrace();
            modelMap.addAttribute(Constants.DEFAULT_SUCCESS_KEY, Boolean.FALSE);
            modelMap.addAttribute(Constants.DEFAULT_ERROR_KEY, e.getMessage());
            logger.error(messages.getMessage("log.error.delete", new String[]{securityUtils.getUserFullName(), messages.getMessage(domain),
                    StringUtils.arrayToDelimitedString((Object[]) ids, "|")}));
        }
        return modelMap;
    }

    @RequestMapping(value = "/enable", method = RequestMethod.POST)
    public @ResponseBody
    ModelMap enable(@RequestParam(value = "ids", required = true) String[] ids) throws SaviorFrameworkException {
        ModelMap modelMap = new ModelMap();
        try {
            Set<Org> orgs = new HashSet<Org>();
            for (String id : ids) {
                Org org = orgService.get(id);
                if (org != null) {
                    org.setEnabled(true);
                    orgs.add(org);
                }
            }
            orgService.update(orgs);
            modelMap.addAttribute(Constants.DEFAULT_SUCCESS_KEY, Boolean.TRUE);
        }
        catch (Exception e) {
            e.printStackTrace();
            modelMap.addAttribute(Constants.DEFAULT_SUCCESS_KEY, Boolean.FALSE);
            modelMap.addAttribute(Constants.DEFAULT_ERROR_KEY, e.getMessage());
        }
        return modelMap;
    }

    /**
     * 停用组织机构
     *
     * @param ids
     * @return
     * @throws SaviorFrameworkException
     */
    @RequestMapping(value = "/disable", method = RequestMethod.POST)
    public @ResponseBody
    ModelMap disable(@RequestParam(value = "ids", required = true) String[] ids) throws SaviorFrameworkException {
        ModelMap modelMap = new ModelMap();
        try {
            Set<Org> orgs = new HashSet<Org>();
            for (String id : ids) {
                Org org = (Org) orgService.get(id);
                if (org != null) {
                    if ((org.getChildren() != null && org.getChildren().size() > 0) || (org.getUsers() != null && org.getUsers().size() > 0)) {
                        modelMap.addAttribute(Constants.DEFAULT_SUCCESS_KEY, Boolean.FALSE);
                        modelMap.addAttribute(Constants.DEFAULT_ERROR_KEY, ErrorCode.DATA_INTEGRITY_VIOLATION + "[" + messages.getMessage("error.constraint.org.disable") + "]");
                        return modelMap;
                    }
                    org.setEnabled(false);
                    orgs.add(org);
                }
            }
            orgService.update(orgs);
            modelMap.addAttribute(Constants.DEFAULT_SUCCESS_KEY, Boolean.TRUE);
        }
        catch (Exception e) {
            e.printStackTrace();
            modelMap.addAttribute(Constants.DEFAULT_SUCCESS_KEY, Boolean.FALSE);
            modelMap.addAttribute(Constants.DEFAULT_ERROR_KEY, e.getMessage());
        }
        return modelMap;
    }


    @RequestMapping(value = "/children", method = RequestMethod.GET)
    @ResponseBody
    public List<Map<String,Object>> children(HttpServletRequest request) throws SaviorFrameworkException, IOException {
        String id = request.getParameter("id");
        List<Map<String, Object>> list = orgService.findByParent(id);
        return list;
    }
}
